<?php
	
	/**
	 * Verifies bootstrapper execution to ensure file
	 * necessities, and disabling direct access
	 */
	defined('ENGINE') or exit;

	/**
	 * User analytics is a solution to give rich insights
	 * to website traffic and marketing effectiveness.  This
	 * object is intended to allow the ability to analyze
	 * all user traffic.
	 */
	final class Module_Users
	{
		/**
		 * Data cache for current user information
		 */
		protected $userinfo		= false;
		
		/**
		 * Private instance to the Engine registry
		 */
		protected $engine;
		
		/**
		 * Constructor
		 */
		public function __construct()
		{
			$this->engine = Engine::init();
			
			/**
			 * GET['LoginAuth'] method, verifies user data
			 * via REQUEST['Email'] and REQUEST['Password'] fields
			 */
			if(isset($_REQUEST['Login']) && isset($_REQUEST['Password']))
			{
				if(!$this->authenticate($_REQUEST['Login'], $_REQUEST['Password'], (isset($_REQUEST['Persistence']) ? true : false)))
				{
					Engine::globals('errors')->append('The username or password you entered is incorrect');
				}
			}
			
			/**
			 * In the event a user has successfully been stored
			 * as a logged in user, the following precaches the
			 * user table, merges permissions, and relates userfields
			 * and userdata to the users account
			 */
			if($this->is_logged())
			{
				$this->userinfo = ($this->userinfo) ? $this->userinfo : $this->fetch_info($this->engine->session->get('userid'));
				
				$this->userinfo->user_permissions = unserialize($this->userinfo->permissions);
				$this->userinfo->usergroup_permissions = unserialize($this->userinfo->usergroup_permissions);
				
				$this->userinfo->permissions = array_merge($this->userinfo->usergroup_permissions, $this->userinfo->user_permissions);
				
				foreach($this->userinfo->permissions as $key => $permissions)
				{
					if(is_array($permissions) && count($permissions))
					{
						$this->userinfo->permissions[$key] = array_unique($permissions);
					}
					else
					{
						$this->userinfo->permissions[$key] = array();
					}
				}
				
				$this->userinfo->permissions = array_filter($this->userinfo->permissions);
			}
		}
		
		/**
		 * Magic get method, this handles overloading of registered 
		 * user information
		 */
		public function __get($name)
		{
			if(array_key_exists($name, (array) $this->userinfo))
			{
				return($this->userinfo->{$name});
			}

			return(false);
		}
		
		/**
		 * Verifies login information and initiates a new login
		 * session based on accurate information
		 */
		protected function authenticate($login = NULL, $password = NULL, $persistent = false)
		{
			if(!is_null($login) && !is_null($password))
			{				
				if(!$login || empty($password))
				{
					return(false);
				}
				
				$userinfo = $this->fetch_info($login, true, true);
				
				if(!$userinfo || !$login || !$this->is_valid_password($password, $userinfo->salt, $userinfo->password))
				{
					return(false);
				}
				
				$this->engine->session->set('userid', $userinfo->id, $persistent);
				
				return($userinfo->id);
			}
			
			return(false);
		}
		
		/**
		 * Removes a users persistent and temporary login
		 * information, logging them out of their account
		 */
		public function logout()
		{
			if($this->engine->session->destroy('userid'))
			{
				return(true);
			}
			
			return(false);

		}
		
		/**
		 * Checks if a user is currently authenticated as a
		 * logged in user
		 */
		public function is_logged()
		{
			if($this->engine->session->get('userid') != false)
			{
				return(true);
			}
			
			return(false);
		}
		
		/**
		 * Hashes a password using a salt reference
		 */
		public function hash($password, $salt)
		{
			return(sha1(sha1($password) . $salt));
		}
		
		/**
		 * Checks if a password matches with its hash value
		 */
		public function is_valid_password($password, $salt, $hash)
		{
			return($this->hash($password, $salt) === $hash);
		}
		
		/**
		 * Fetchs user information for a specific user.
		 */
		protected function fetch_info($identifier, $by_email = false, $cache_info = false)
		{
			$identifier	= (string) $this->engine->db->escape($identifier);
			$by_email	= (bool) $by_email;
			
			if($this->userinfo !== false && (!$by_email && $this->userinfo->id == $identifier || $by_email && $this->userinfo->email == $identifier))
			{
				return($this->userinfo);
			}
			
			$query = $this->engine->db->query("SELECT `" . PREFIX . "users`.*, `" . PREFIX . "usergroups`.`title` AS `usergroup_title`, `" . PREFIX . "usergroups`.`permissions` AS `usergroup_permissions`, `" . PREFIX . "usergroups`.`hierarchy` AS `usergroup_hierarchy`  FROM `" . PREFIX . "users` INNER JOIN `" . PREFIX . "usergroups` ON (`" . PREFIX . "users`.`usergroup_id` = `" . PREFIX . "usergroups`.`id`) WHERE " . ($by_email ? "`" . PREFIX . "users`.`email` = '" . $identifier . "'" : "`" . PREFIX . "users`.`id` = '" . $identifier . "'") . "");
			
			if(!$query || !$query->num_rows())
			{
				return(false);
			}
			else if(!($userinfo = $query->fetch_object()))
			{
				return(false);
			}
			
			if($cache_info)
			{
				return($this->userinfo = $userinfo);
			}
			
			return($userinfo);
		}
	}

?>